#include <memory>
#include <mutex>
#include <thread>

namespace ape {
template <class T> class shared_ptr {

private:
    T* _ptr;
    int* _pcount;
    mutex* _pmtx;
    function<void(T*)> _del = [](T* ptr) { delete ptr; };

public:
    // 构造函数
    shared_ptr(T* ptr = nullptr)
        : _ptr(ptr), _pcount(new int(1)), _pmtx(new mutex) {}

    // 删除器构造函数
    template <class D>
    shared_ptr(T* ptr, D del)
        : _ptr(ptr), _pcount(new int(1)), _pmtx(new mutex), _del(del) {}

    // 删除器Release()
    void Release() {
        _pmtx->lock();
        bool deleteFlag = false;

        if (--(*_pcount) == 0) {
            if (_ptr != nullptr) {
                _del(_ptr);
            }

            delete _pcount;
            deleteFlag = true;
        }

        _pmtx->unlock();

        if (deleteFlag) {
            delete _pmtx;
        }
    }
    void AddCount() {
        _pmtx->lock();

        ++(*_pcount);

        _pmtx->unlock();
    }

    // 拷贝构造
    shared_ptr(const shared_ptr<T>& sp)
        : _ptr(sp._ptr), _pcount(sp._pcount), _pmtx(sp._pmtx) {
        AddCount();
    }

    // 赋值重载
    // 1."自己"给"自己"赋值
    // 不仅仅是p1 = p1 还要考虑p2 = p1 但之前p2就 = p1
    // 2.左 = 右 赋值后
    //  左指针指向空间的指针少了一个 左指针的count--
    //  进一步考虑count--后==0的情况 右指针指向空间的指针多了一个
    //  右指针的count++
    shared_ptr<T>& operator=(const shared_ptr<T>& sp) {
        //"自己"给"自己"赋值: "自己"的本质
        if (_ptr != sp._ptr) {
            // count--
            Release();

            _ptr = sp._ptr;
            _pcount = sp._pcount;
            _pmtx = sp._pmtx;

            // count++
            AddCount();
        }

        return *this;
    }

    // 析构函数
    ~shared_ptr() { Release(); }

    T& operator*() { return *_ptr; }

    T* operator->() { return _ptr; }

    T* GetPtr() const { return _ptr; }

    int GetCount() const { return *_pcount; }
};
} // namespace ape